//线程池就是提前维护一个线程数组，和一个任务队列，不停地让线程去完成队列里的任务

#include<iostream>
#include<thread>
#include<mutex>
#include<queue>
#include<string>
#include<vector>
#include<functional>
#include<condition_variable>


class ThreadPool
{
public:
	ThreadPool(int numThreads) :stop(false)
	{
		for (int i = 0; i < numThreads; i++)
		{
			threads.emplace_back([this]		//加入线程入口函数用,lambda表达式实现
				{
					while (1)
					{
						std::unique_lock<std::mutex> lock(mtx);
						condition.wait(lock, [this]
							{
								return !tasks.empty() || stop;
							});
						if (stop && tasks.empty())	//如果线程任务全部完成中止，直接return
						{
							return;
						}

						std::function<void()> task(std::move(tasks.front()));		//取出列表最左边任务
						tasks.pop();	//将任务从列表中移除
						task();			//解锁
					}
				});		
		}
	}

	~ThreadPool()
	{
		{
			std::unique_lock<std::mutex> lock(mtx);
			stop = true;
		}

		condition.notify_all();
		for (auto& t : threads)
		{
			t.join();
		}
	}

	template<class F, class... Args>	//函数模板
	void enqueue(F&& f, Args&&... args)	//在函数模板中右值引用就是万能引用
	{
		std::function<void()> task =
			std::bind(std::forward<F>(f), std::forward<Args>(args)...);     //forward完美转换，bind函数适配器
		{
			std::unique_lock<std::mutex> lock(mtx);
			tasks.emplace(std::move(task));
		}

		condition.notify_one();
	}
private:
	std::vector<std::thread> threads;				//线程池
	std::queue < std::function<void()>> tasks;		//任务队列

	std::mutex mtx;
	std::condition_variable condition;

	bool stop;
};


int main()
{
	ThreadPool pool(4);

	for (int i = 0; i < 10; i++)
	{
		pool.enqueue([i] {
			std::cout << "task: " << i << " is running. " << std::endl;
			std::this_thread::sleep_for(std::chrono::microseconds(100));
			std::cout << "task: " << i << " is finished. " << std::endl;
			});
	}

	return 0;
}